package edu.uci.ics.multicast.overlay;

import java.io.File;
import java.util.Iterator;
import java.util.StringTokenizer;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ImportTopology {

	static final int TOTAL_NUMBER_OF_OVERLAY_NODES = 100;
	
	private static final String XML_MODEL = "data/kbkim_htr_1000n.model";
	private static final String XML_GRAPH = "data/kbkim_htr_1000n.graph";
	private static final String XML_ROUTE = "data/kbkim_htr_1000n.route";

	private Topology topology;

	public ImportTopology(Topology topology) {
		this.topology = topology;
	}

	public void load() throws DocumentException {
		SAXReader reader = new SAXReader();
		Document document = null;

		// read Model
		document = reader.read(new File(XML_MODEL));
		readModel(document.getRootElement());

		// read Graph
		document = reader.read(new File(XML_GRAPH));
		readGraph(document.getRootElement());

		// read Route
		document = reader.read(new File(XML_ROUTE));
		readRoute(document.getRootElement());
	}

	private void readModel(Element root) {
		Element elements = root.element("emulators").element("emul").element("host");
		String hostname = elements.attributeValue("hostname");
		if ("coie01".equals(hostname)) {
			elements = elements.element("subnet");
			int numberofNodes = 0;
			for (Iterator i = elements.elementIterator(); i.hasNext();) {
				Element element = (Element) i.next();
				String idx = element.attributeValue("int_idx");
				String vn = element.attributeValue("int_vn");
				String vip = element.attributeValue("vip");
				topology.addOverlayNode(new OverlayNode(idx,vn,vip));
				numberofNodes++; 
				if (numberofNodes >= TOTAL_NUMBER_OF_OVERLAY_NODES ) {
					return; 
				}
			}
			return;
		} else {
			return;
		}
	}

	private void readGraph(Element root) {
		Element elements = root.element("vertices");
		for (Iterator i = elements.elementIterator(); i.hasNext();) {
			Element element = (Element) i.next();
			String role = element.attributeValue("role");
			if (!"virtnode".equals(role)) { // physical nodes (transit,gateway)
				String idx = element.attributeValue("int_idx");
				double x = Double.parseDouble(element.attributeValue("dbl_x"));
				double y = Double.parseDouble(element.attributeValue("dbl_y"));
				topology.addPhysicalNode(new PhysicalNode(idx,x,y));
			}
		}
		elements = root.element("edges");
		for (Iterator i = elements.elementIterator(); i.hasNext();) {
			Element element = (Element) i.next();
			double kbps = Double.parseDouble(element.attributeValue("dbl_kbps"));
			double delay = Double.parseDouble(element.attributeValue("int_delayms"));
			String strDestination = element.attributeValue("int_dst");
			String index = element.attributeValue("int_idx");
			String strSource = element.attributeValue("int_src");
			
			MulticastNode sourceNode = topology.getMulticastNode(strSource);
			MulticastNode destinationNode = topology.getMulticastNode(strDestination);
			
			topology.addEdge(new Edge(index,kbps,delay,sourceNode,destinationNode));
		}
	}
	
	private void readRoute(Element root) {
		Element elements = root;
		for (Iterator i = elements.elementIterator(); i.hasNext();) {
			Element element = (Element) i.next();
			String strDestinationVirtualIndex = element.attributeValue("int_vndst");
			String strSourceVirtualIndex = element.attributeValue("int_vnsrc");
			
			OverlayNode sourceVirtualIndex = topology.getOverlayNodeByVirtualIndex(strSourceVirtualIndex);
			OverlayNode destinationVirtualIndex = topology.getOverlayNodeByVirtualIndex(strDestinationVirtualIndex); 
			
			if (sourceVirtualIndex!=null && destinationVirtualIndex!=null) {
				Path path = new Path(destinationVirtualIndex);
				String hops = element.attributeValue("hops");
				StringTokenizer st = new StringTokenizer(hops," ");
				while ( st.hasMoreTokens() ) {
				  String strEdge = (String)st.nextToken();
				  Edge edge = topology.getEdgeByIndex(strEdge);
				  path.addEdge(edge);
				}
				sourceVirtualIndex.addPath(path);
			}
		}
	}

}
